package com.pxxy.springmvc.interceptor;

import org.springframework.core.NamedThreadLocal;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/************
 * 请求URL执行的性能日志拦截器
 */
public class PerformanceLogInterceptor extends HandlerInterceptorAdapter {
    //此属性是基于线程ID来绑定对象的,ThreadLocal相当于是Key是线程ID的Map,所以，它是一个容器类
    private NamedThreadLocal<Long> timer = new NamedThreadLocal<>("ptime");

    /**************
     * 在目前Controller方法执行之前调用，我们在此方法记录系统时间，
     * 由于拦截器是单例的，所以，我们需要把这个时间绑定到 ThreadLocal中去。
     * @param request
     * @param response
     * @param handler
     * @return 返回true,表示执行拦截器链中下一个拦截器，返回false,则中断执行
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws Exception {
        //1. 记录下当前的系统时间
        long startTime = System.currentTimeMillis();
        //2. 把这个时间绑定到 NamedThreadLocal中去
        timer.set(startTime);
        //3.返回
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //1. 记录当前系统时间
        long endTime = System.currentTimeMillis();
        //2. 通过ThreadLocal来取出当前线程的起始时间
        long startTime = timer.get();
        //3. 两个时间差
        long cost = endTime - startTime;
        //
        String uri = request.getRequestURI();
        //
        if(uri.startsWith(request.getContextPath()+"/static")) {
            return ;
        }
        //4. 判断
        if(cost > 300) { // 这个阀值是可以根据需求自己设定的
            //记录日志
            System.out.printf(">>>> 请求：%s 花费的时间是：%d ms.\n", request.getRequestURI(),cost);
        } else {
            System.out.printf(">>> 请求：%s 所费时间是在性能要求的阀值之内的\n", request.getRequestURI());
        }
    }
}
